#pragma once

#include "Robot.h"

#using <System.dll>

using namespace System;
using namespace System::IO;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Text;
using namespace System::Threading;

namespace RobotCollisionDetection {
	
	/**
	 * @brief Klasa reprezentujaca polaczenie TCP pomiedzy aplikacja na PC a robotem.
	 *
	 * Kazde polaczenie TCP powinno dzialac w osobnym watku wykorzystujac metody AcceptAndListen lub ConnectAndListen
	 */
	public ref class TcpConnection
	{
	public:
		
		/**
		* statyczna Tablica przechowujaca obiekty TcpConnection
		*/
		static Collections::ArrayList^ ConnectionArray = gcnew Collections::ArrayList();

		/// konstruktor - przypisuje host i port
		TcpConnection(String^ host, String^ port, Robot * robot);

		/**
		 * Glowna metoda w trybie dzialania jako serwer.
		 * @n Czeka na polaczenie i jesli zaakceptuje polaczenie to zaczyna odbierac i parsowac dane w nieskonczonej petli
		 */
		void AcceptAndListen();

		/**
		 * Glowna metoda w trybie dzialania jako klient.
		 * @n Probuje sie polaczyc i jesli sie uda to zaczyna odbierac i parsowac dane w nieskonczonej petli
		 */
		void ConnectAndListen();

		/// obiekt reprezentujacy dany watek
		Thread^ tcpThread;

		/// wskaznik do robota skorelowanego z polaczeniem TCP
		Robot * robot;

		/// klasa reprezentujaca typ polaczenia: Client/Server
		enum class TcpMode{Client, Server};
		
		static void CloseAndRemove(int i);
	protected:

	private:
		/// strumien przypisany do socketa
		NetworkStream^ stream;

		/// metoda parsujaca odebrane bajty na polozenie robota
		void ReadPositions();
		
		/// timeout odczytu danych z robotow w milisekundach
		static const int readTimeout = 200;

		/// czas w milisekundach przerwy miedzy kolejnymi odczytami danych z robotow
		static const int sleepTime = 100;		

		/**
		 * adres IP robota, z ktorym chcemy sie laczyc (w trybie klient)
		 * lub adres, na ktorym nasluchujemy (w trybie serwer)
		 */
		String^ host;

		/// port, na ktorym chcemy sie polaczyc
		String^ port;
	};
}
